package com.beiding.fastmock.fram;

import jdk.nashorn.api.scripting.ScriptObjectMirror;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 丁常磊
 * @date 2021/7/14 15:04
 */


@Component
@Slf4j
public class ScriptFileHolder implements FileChecker.ChangeCallback {
    private FileChecker fileChecker;
    private File root;

    /**
     * 当前执行所在目录
     */
    private File currentDir;

    @Autowired
    private Configurator configurator;
    @Autowired
    private ScriptExecutor scriptExecutor;

    public void changeScriptRoot(File file) {
        try {
            log.info("变更脚本目录{}", file.getCanonicalFile().getAbsolutePath());
        } catch (Exception ignore) {
        }
        this.checkFile(file);
        this.root = file;
        this.currentDir = this.root;
        if (this.fileChecker != null) {
            this.fileChecker.close();
        }
        this.fileChecker = new FileChecker(file);
        this.fileChecker.setChangeCallback(this);
        this.fileChecker.start();
        log.info("变更脚本目录成功");
    }

    private void checkFile(File file) {
        if (!file.isDirectory()) {
            error("必须是文件夹");
        }
        if (!new File(file, "index.js").exists()) {
            error("缺少index.js文件");
        }
    }

    @Override
    public void onChange() {
        TaskCenter.antiShake("重置脚本环境", () -> {
            loadFile("index");
            log.info("重置完成");
        }, 100);
    }

    private void error(String msg) {
        throw new RuntimeException(msg);
    }

    @Value("${script-root}")
    private String scriptRoot;

    @PostConstruct
    public void init() {
        changeScriptRoot(new File(scriptRoot));
        onChange();
    }

    public void runCmd(String cmd,File dir) {
        try {
            Runtime.getRuntime().exec(cmd, null, dir);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Object loadFile(String path) {

        File targetFile=null;

        String jsPath = path;

        if (!jsPath.endsWith(".js")) {
            jsPath = jsPath + ".js";
        }

        File indexFile = new File(currentDir, jsPath);

        if (indexFile.isFile()) {
            targetFile = indexFile;
        }

        if (targetFile == null) {

            File file = new File(currentDir, path);
            if (file.isDirectory()) {
                File indexF = new File(file, "index.js");
                if (indexF.isFile()) {
                    targetFile = indexF;
                }
            }

        }

        if (targetFile == null) {
            throw new IllegalArgumentException("未找到可执行文件:" + path);
        }

        File cd = currentDir;

        //切换当前目录
        currentDir = targetFile.getParentFile();

        //载入相对路径
        try {

            ScriptObjectMirror func = (ScriptObjectMirror) scriptExecutor.exe(targetFile.getPath().replace("\\","/"), configurator.bindings);

            //放入相对路径
            Map<String, Object> evn = new HashMap<>();
            evn.put("$dir", currentDir);
            return func.call(targetFile, configurator,evn);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            currentDir = cd;
        }
    }


    public File getCurrentDir() {
        return currentDir;
    }

    public File getRoot() {
        return root;
    }
}
